<!DOCTYPE html>
<html>
<head>
    <title>影子出价模拟</title>
    <!-- 这里可以添加 CSS 和 JavaScript 的链接 -->
    <script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
    <style>

    body, html {
        margin: 0;
        padding: 0;
        height: auto; /* 设置为 auto 以允许页面根据内容伸缩 */
      }

      body {
        font-family: Arial, sans-serif;
        background-color: #f4f4f4;
        display: flex;
        justify-content: center;
        align-items: flex-start; /* 从顶部开始排列内容 */
        padding-top: 20px; /* 添加一些顶部空间 */
        min-height: 100vh; /* 确保至少全屏高度 */
      }

  .container {
    background-color: white;
    padding: 20px;
    border-radius: 8px;
    box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
    width: 80%;
    max-width: 600px;
    margin-bottom: 20px; /* 添加底部空间 */
  }

      h1 {
        text-align: center;
        color: #333;
      }

      .form-group {
        margin-bottom: 20px;
      }

      label {
        display: block;
        margin-bottom: 10px;
      }

      input[type="number"] {
        width: 100%;
        padding: 10px;
        margin-top: 5px;
        border: 1px solid #ddd;
        border-radius: 4px;
        box-sizing: border-box;
      }

      button {
        background-color: #0056b3;
        color: white;
        padding: 10px 15px;
        border: none;
        border-radius: 4px;
        cursor: pointer;
        margin-top: 20px;
        width: 100%;
      }

      button:hover {
        background-color: #004494;
      }

      #results {
        margin-top: 20px;
        padding: 10px;
        background-color: #eaeaea;
        border-radius: 4px;
      }

      #chart {
        margin-top: 20px;
      }

      canvas {
        width: 100% !important;
        height: auto !important;
      }
    </style>


</head>
<body>
    <div class="container">
        <h1>影子出价模拟器</h1>
        <!-- 表单输入区 -->
        <div class="form-group">
            <!-- 输入字段 -->
            <label>ALPHA: <input type="number" id="alpha" step="0.1" value="0.2"></label>
            <label>BETA: <input type="number" id="beta" step="0.1" value="0.15"></label>
            <label>最小出价次数: <input type="number" id="minBidCount" value="1"></label>
            <label>最大出价次数: <input type="number" id="maxBidCount" value="30"></label>
            <label>起拍价: <input type="number" id="startPrice" step="10" value="100"></label>
            <label>当前最高出价: <input type="number" id="currentPrice" step="10" value="180"></label>
            <label>最低评估价: <input type="number" id="minPrice" step="10" value="80"></label>
            <label>最高评估价: <input type="number" id="maxPrice" step="10" value="200"></label>
        </div>

        <!-- 按钮 -->
        <button onclick="runSimulation()">生成出价</button>
        
        <!-- 输出结果 -->
        <div id="results">
            <p id="bidCount"></p>
            <p id="originalBids"></p>
            <p id="adjustedBids"></p>
        </div>
    </div>
    <script>
        // 在这里插入 JavaScript 代码

        const referenceValues = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100,105,110,115,120,125,130,135,140,145,150,155,160,165,170,175,180,185,190,195,200,210,220,230,240,250,260,270,280,290,300,310,320,330,340,350,360,370,380,390,400,410,420,430,440,450,460,470,480,490,500,510,520,530,540,550,560,570,580,590,600,610,620,630,640,650,660,670,680,690,700,710,720,730,740,750,760,770,780,790,800,810,820,830,840,850,860,870,880,890,900,910,920,930,940,950,960,970,980,990,666,888,1000,1050,1100,1150,1200,1250,1300,1350,1400,1450,1500,1550,1600,1650,1700,1750,1800,1850,1900,1950,2000,2050,2100,2150,2200,2250,2300,2350,2400,2450,2500,2550,2600,2650,2700,2750,2800,2850,2900,2950,3000,1666,2666,1888,2888,3100,3200,3300,3400,3500,3600,3700,3800,3900,4000,4100,4200,4300,4400,4500,4600,4700,4800,4900,5000,5100,5200,5300,5400,5500,5600,5700,5800,5900,6000,6100,6200,6300,6400,6500,6600,6700,6800,6900,7000,7100,7200,7300,7400,7500,7600,7700,7800,7900,8000,8100,8200,8300,8400,8500,8600,8700,8800,8900,9000,9100,9200,9300,9400,9500,9600,9700,9800,9900,3666,4666,5666,6666,7666,8666,9666,3888,4888,5888,6888,7888,8888,9888,10000,10500,11000,11500,12000,12500,13000,13500,14000,14500,15000,15500,16000,16500,17000,17500,18000,18500,19000,19500,20000,20500,21000,21500,22000,22500,23000,23500,24000,24500,25000,25500,26000,26500,27000,27500,28000,28500,29000,29500,30000,30500,31000,31500,32000,32500,33000,33500,34000,34500,35000,35500,36000,36500,37000,37500,38000,38500,39000,39500,40000,40500,41000,41500,42000,42500,43000,43500,44000,44500,45000,45500,46000,46500,47000,47500,48000,48500,49000,49500,50000,50500,51000,51500,52000,52500,53000,53500,54000,54500,55000,55500,56000,56500,57000,57500,58000,58500,59000,59500,60000,60500,61000,61500,62000,62500,63000,63500,64000,64500,65000,65500,66000,66500,67000,67500,68000,68500,69000,69500,70000,70500,71000,71500,72000,72500,73000,73500,74000,74500,75000,75500,76000,76500,77000,77500,78000,78500,79000,79500,80000,80500,81000,81500,82000,82500,83000,83500,84000,84500,85000,85500,86000,86500,87000,87500,88000,88500,89000,89500,90000,90500,91000,91500,92000,92500,93000,93500,94000,94500,95000,95500,96000,96500,97000,97500,98000,98500,99000,99500,100000,100500,101000,101500,102000,102500,103000,103500,104000,104500,105000,105500,106000,106500,107000,107500,108000,108500,109000];


        function findClosestValue(value, referenceValues) {
            return referenceValues.reduce((prev, curr) => (Math.abs(curr - value) < Math.abs(prev - value) ? curr : prev));
        }

        function replaceWithClosestValues(bidArrays, referenceValues) {
            return bidArrays.map(value => findClosestValue(value, referenceValues));
        }


        function runSimulation() {
            // const updatedBidArrays = [];
            //const bidArrays = [];
            //const bidCount = 0;

            // 读取输入值
            const ALPHA = parseFloat(document.getElementById('alpha').value);
            const BETA = parseFloat(document.getElementById('beta').value);
            const MIN_BID_COUNT = parseInt(document.getElementById('minBidCount').value);
            const MAX_BID_COUNT = parseInt(document.getElementById('maxBidCount').value);
            const startPrice = parseFloat(document.getElementById('startPrice').value);
            const currentPrice = parseFloat(document.getElementById('currentPrice').value);
            const minPrice = parseFloat(document.getElementById('minPrice').value);
            const maxPrice = parseFloat(document.getElementById('maxPrice').value);

            // 执行模拟
            const { bidCount, bidArrays } = generateSimulatedBids(startPrice, currentPrice, minPrice, maxPrice, ALPHA, BETA, MIN_BID_COUNT, MAX_BID_COUNT);
            // 替换出价
            const updatedBidArrays = replaceWithClosestValues(bidArrays, referenceValues);

            // 更新结果显示
            document.getElementById('results').innerHTML = `
                <p><b>出价次数: </b><br>${bidCount}</p>
                <p><b>计算出的原始出价价格: </b><br>[${bidArrays.join(', ')}]</p>
                <p><b>价格库换算后的出价价格: </b><br>[${updatedBidArrays.join(', ')}]</p>
            `;
            // 使其在全局范围内可用
            window.updatedBidArrays = updatedBidArrays;
        }


        function calculateBidCount(currentPrice, minPrice, MIN_BID_COUNT, MAX_BID_COUNT) {
            const heatFactor = calculateHeatFactor(currentPrice, minPrice);
            let bidCount = Math.round(MIN_BID_COUNT + (heatFactor - 1) * (MAX_BID_COUNT - MIN_BID_COUNT));
            return Math.min(Math.max(bidCount, MIN_BID_COUNT), MAX_BID_COUNT);
        }

        function calculateHeatFactor(currentPrice, minPrice) {
            return currentPrice / minPrice;
        }

        function calculateLowerBound(startPrice, currentPrice, maxPrice, heatFactor, ALPHA) {
            let adjustedLowerBound = startPrice + ALPHA * (heatFactor - 1) * (maxPrice - startPrice);
            // 确保 lowerBound 不超过 currentPrice 且不低于 startPrice
            adjustedLowerBound = Math.min(adjustedLowerBound, currentPrice);
            return Math.max(startPrice, adjustedLowerBound);
        }

        function generateNormalDistributionBid(lowerBound, upperBound, BETA) {
            const mean = (lowerBound + upperBound) / 2;
            const standardDeviation = BETA * (upperBound - lowerBound);
            let bid, attempts = 0, maxAttempts = 100;

            do {
                bid = mean + normalRandom() * standardDeviation;
                attempts++;
                if (attempts > maxAttempts) {
                    // 如果超过最大尝试次数，返回边界值之一
                    return (Math.random() < 0.5) ? lowerBound : upperBound;
                }
            } while (bid < lowerBound || bid > upperBound);

            return bid;
        }


        function normalRandom() {
            let u = 0, v = 0;
            while(u === 0) u = Math.random();
            while(v === 0) v = Math.random();
            return Math.sqrt(-2.0 * Math.log(u)) * Math.cos(2.0 * Math.PI * v);
        }

        function generateSimulatedBids(startPrice, currentPrice, minPrice, maxPrice, ALPHA, BETA, MIN_BID_COUNT, MAX_BID_COUNT) {
            const bidCount = calculateBidCount(currentPrice, minPrice, MIN_BID_COUNT, MAX_BID_COUNT);
            const bidArrays = [];
            for (let i = 0; i < bidCount; i++) {
                const heatFactor = calculateHeatFactor(currentPrice, minPrice);
                const lowerBound = calculateLowerBound(startPrice, currentPrice, maxPrice, heatFactor, ALPHA);
                const upperBound = currentPrice;
                const simulatedBid = generateNormalDistributionBid(lowerBound, upperBound, BETA);
                bidArrays.push(Number(simulatedBid.toFixed(2)));
            }
            return { bidCount, bidArrays };
        }

    </script>
</body>
</html>
